package com.ficus.road.maintain.service;

import com.ficus.road.maintain.authority.service.UserService;
import com.ficus.road.maintain.authority.utils.SecurityUtils;
import com.ficus.road.maintain.authority.vo.LoginResponse;
import com.ficus.road.maintain.core.model.Confirmation;
import com.ficus.road.maintain.core.model.Hit;
import com.ficus.road.maintain.core.model.statistic.StatisticByTypeRequest;
import com.ficus.road.maintain.core.model.statistic.StatisticMonthRequest;
import com.ficus.road.maintain.core.model.statistic.StatisticMonthResponse;
import com.ficus.road.maintain.dao.HitDao;
import com.ficus.road.maintain.dto.StatusStatisticResponse;
import com.ficus.road.maintain.util.DateUtil;
import com.ficus.road.maintain.util.MyDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;

@Service
@Slf4j
public class HitStatisticService {

    @Autowired
    HitDao hitDao;

    @Autowired
    UserService userService;

    public static final String month_dateFormat_mongo = "%Y-%m";

    public List<StatisticMonthResponse> trendMonth(StatisticMonthRequest request) {
        //获取当前用户的角色信息
        UserDetails currentUser = SecurityUtils.getCurrentUser();
        LoginResponse loginResponse = userService.queryLoginInfoByUsername(currentUser.getUsername());
        Criteria criteria = Criteria.where("hit_time")
                .gt(DateUtil.getMonthStart(MyDateUtil.strParseDate(request.getStartMonth(), "yyyy-MM")).getTime() / 1000)
                .lt(DateUtil.getMonthEnd(MyDateUtil.strParseDate(request.getEndMonth(), "yyyy-MM")).getTime() / 1000)
                .and("attrs.confirmation.status").is(Confirmation.ConfirmationStatus.CORRECT)
                .and("create_time").exists(true)
                .and("attrs.car_id").in(loginResponse.getCarIdList());

//        ProjectionOperation project = Aggregation.project().and(DateOperators.DateToString.dateOf("creation_time")
//        ProjectionOperation month = project()
//                .andExpression("dateToString('%Y-%m', toDate(hit_time * 1000)").as("month");
////                .andExpression("{$dateToString:{date:{$multiply:{'$hit_time',1000}}, format:'%Y-%m'}}").as("month");
//        ProjectionOperation month = project("hit_time")
//                .andExpression("{$dateToString:{date:{$add:{$multiply:{'$hit_time', 1000},[0]}}, format:'%Y-%m'}}", new Date(2880000)).as("month");
//        ProjectionOperation month1 = project("hit_time")
//                .andExpression("{" +
//                                            "$dateToString:{" +
//                                                 "date:{" +
//                                                    "$convert:{" +
//                                                    "input:{'$multiply':['$hit_time',1000]},to: 'date'}" +
//                                                 "}," +
//                                                 "format:'%Y-%m'" +
//                                            "}" +
//                                        "}"
//                ).as("month");
//        ProjectionOperation project = project().add.and(
//                        DateOperators.DateToString.dateOf(Add.new Date(0))
//                DateOperators.Second.secondOf(
//                                "hit_time").to
//                        .toString(month_dateFormat_mongo))
////                        .withTimezone(DateOperators.Timezone.valueOf("Asia/Shanghai")))
//                .as("month");
        //{'$multiply': ['$created_at', 1000] }
//        ArithmeticOperators.Multiply multiply =
//                ArithmeticOperators.Multiply.valueOf("hit_time").multiplyBy(1000);
//        ConvertOperators.Convert date = ConvertOperators.Convert.convertValue(multiply).to("date");
//        DateOperators.DateToString dateToString = DateOperators.DateToString.dateOf(date).toString(month_dateFormat_mongo);
//                        .withTimezone(DateOperators.Timezone.valueOf("Asia/Shanghai")
//                        );
//        ProjectionOperation projectionOperation1 = project().and(dateToString).as("month");
//
//
//        ProjectionOperation projectionOperation = project("hit_time")
//                .andExpression("toDate(hit_time * 1000)").as("date"); // 将时间戳乘以1000（转换为毫秒数），然后使用 toDate() 函数将其转换为日期类型，并储存为名为 date 的新字段
//        ProjectionOperation projectionOperation2 = project("date").andExpression("$dateToString", "format('%Y-%m', '$date')").as("month");// 使用 $dateToString 操作符将日期格式化为指定字符串格式，储存为名为 dateString 的新字段
        ProjectionOperation project = Aggregation.project().and(DateOperators.DateToString.dateOf("create_time")
                        .toString(month_dateFormat_mongo))
//                        .withTimezone(DateOperators.Timezone.valueOf("Asia/Shanghai")))
                .as("month");
        GroupOperation groupOperation = Aggregation.group("month").first("month").as("month").count().as("count");
        MatchOperation totalMatch = Aggregation.match(criteria);
        Aggregation totalAggregation = newAggregation(totalMatch, project, groupOperation);
        return hitDao.findAggregateList(totalAggregation, StatisticMonthResponse.class);
    }

    @Scheduled(fixedDelay = 60000)
    public void test(){
        Query query = new Query(Criteria.where("create_time").exists(false));
        query.fields().include("_id");
        query.fields().include("hit_time");
        query.limit(10000);
        List<Hit> byQuery;
        do {
            byQuery= hitDao.findByQuery(query);
            byQuery.forEach(hit ->{
                hitDao.update(hit.getId(), Update.update("create_time", new Date(hit.getHitTime() * 1000)));
            });
        }while (byQuery.size() > 0);
    }
    public List<StatusStatisticResponse> statisticByType(StatisticByTypeRequest request) {
        //获取当前用户的角色信息
        UserDetails currentUser = SecurityUtils.getCurrentUser();
        LoginResponse loginResponse = userService.queryLoginInfoByUsername(currentUser.getUsername());
        Criteria criteria = Criteria.where("hit_time").gt(request.getStartTime()).lt(request.getEndTime())
                .and("attrs.confirmation.status").is(Confirmation.ConfirmationStatus.CORRECT)
                .and("attrs.car_id").in(loginResponse.getCarIdList());
        GroupOperation groupOperation = Aggregation.group("type").first("type").as("type").count().as("count");

        MatchOperation totalMatch = Aggregation.match(criteria);
        Aggregation totalAggregation = newAggregation(totalMatch, groupOperation);
        return hitDao.findAggregateList(totalAggregation, StatusStatisticResponse.class)
                .stream().sorted(Comparator.comparingLong(StatusStatisticResponse::getCount).reversed())
                .collect(Collectors.toList());

    }
}
